/*
 *     Prionace - A file navigator to manage your files
 *
 *     Copyright (C) 2012 Francivan Bezerra
 *
 *     This file is part of Prionace.
 *
 *     Prionace is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     Prionace is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with Prionace.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.fba.prionace.ui.viewer;

import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;

public class TransitionEffect {

	public static final int DISAPPEAR = 0;

	public static final int APPEAR = 1;

	public static final int NONE = 0;

	public static final int ZOOM_IN = 1;

	public static final int ZOOM_OUT = 2;

	public static final int SLIDE = 3;

	private Component canvasArea;

	public TransitionEffect() {
	}

	public TransitionEffect(Component canvasArea) {
		setCanvasArea(canvasArea);
	}

	public Component getCanvasArea() {
		return canvasArea;
	}

	public void setCanvasArea(Component canvasArea) {
		this.canvasArea = canvasArea;
	}

	public void doEffect(int type, int action) {
		switch (type) {
		case ZOOM_IN:
			zoomIn(action);
			break;
		case ZOOM_OUT:
			zoomOut(action);
			break;
		case SLIDE:
			slide(action);
		}
	}

	public void zoomIn(int action) {
		if (canvasArea == null || canvasArea.getSize().width == 0
				|| canvasArea.getSize().height == 0) {
			return;
		}

		double scale;
		double initialScale;
		double finalScale;
		double scaleRatio;

		BufferedImage initialCanvas = new BufferedImage(
				canvasArea.getSize().width, canvasArea.getSize().height,
				BufferedImage.TYPE_INT_ARGB);
		BufferedImage frameBuffer = new BufferedImage(
				canvasArea.getSize().width, canvasArea.getSize().height,
				BufferedImage.TYPE_INT_ARGB);

		Graphics2D initialCanvasGC = (Graphics2D) initialCanvas
				.createGraphics();
		Graphics2D frameBufferGC = (Graphics2D) frameBuffer.createGraphics();
		Graphics2D canvasAreaGC = (Graphics2D) canvasArea.getGraphics();
		AffineTransform transform = new AffineTransform();

		canvasArea.paintAll(initialCanvasGC);
		frameBufferGC.setColor(canvasArea.getComponentAt(0, 0).getBackground());

		if (action == DISAPPEAR) {
			initialScale = 1d;
			finalScale = 10d;
			scaleRatio = 1d;
		} else {
			initialScale = 0d;
			finalScale = 1d;
			scaleRatio = .1d;
		}

		scale = initialScale;
		while (scale < finalScale) {
			scale += scaleRatio;
			transform.setTransform(scale, 0d, 0d, scale,
					(double) -canvasArea.getWidth() * (scale - 1d) / 2,
					(double) -canvasArea.getHeight() * (scale - 1d) / 2);
			frameBufferGC.fillRect(0, 0, frameBuffer.getWidth(),
					frameBuffer.getHeight());
			frameBufferGC.drawImage(initialCanvas, transform, canvasArea);
			canvasAreaGC.drawImage(frameBuffer, 0, 0, canvasArea);
			frameBuffer.flush();
		}

		if (action == DISAPPEAR) {
			frameBufferGC.fillRect(0, 0, frameBuffer.getWidth(),
					frameBuffer.getHeight());
			canvasAreaGC.drawImage(frameBuffer, 0, 0, canvasArea);
		}

		initialCanvas.flush();
	}

	public void zoomOut(int action) {
		if (canvasArea == null || canvasArea.getSize().width == 0
				|| canvasArea.getSize().height == 0) {
			return;
		}

		double scale;
		double initialScale;
		double finalScale;
		double scaleRatio;

		BufferedImage initialCanvas = new BufferedImage(
				canvasArea.getSize().width, canvasArea.getSize().height,
				BufferedImage.TYPE_INT_ARGB);
		BufferedImage frameBuffer = new BufferedImage(
				canvasArea.getSize().width, canvasArea.getSize().height,
				BufferedImage.TYPE_INT_ARGB);

		Graphics2D initialCanvasGC = (Graphics2D) initialCanvas
				.createGraphics();
		Graphics2D frameBufferGC = (Graphics2D) frameBuffer.createGraphics();
		Graphics2D canvasAreaGC = (Graphics2D) canvasArea.getGraphics();
		AffineTransform transform = new AffineTransform();

		canvasArea.paintAll(initialCanvasGC);
		frameBufferGC.setColor(canvasArea.getComponentAt(0, 0).getBackground());

		if (action == DISAPPEAR) {
			initialScale = 1d;
			finalScale = 0d;
			scaleRatio = .1d;
		} else {
			initialScale = 10d;
			finalScale = 1d;
			scaleRatio = 1d;
		}

		scale = initialScale;
		while (scale > finalScale) {
			scale -= scaleRatio;
			transform.setTransform(scale, 0d, 0d, scale,
					(double) -canvasArea.getWidth() * (scale - 1d) / 2,
					(double) -canvasArea.getHeight() * (scale - 1d) / 2);
			frameBufferGC.fillRect(0, 0, frameBuffer.getWidth(),
					frameBuffer.getHeight());
			frameBufferGC.drawImage(initialCanvas, transform, canvasArea);
			canvasAreaGC.drawImage(frameBuffer, 0, 0, canvasArea);
			frameBuffer.flush();
		}

		if (action == DISAPPEAR) {
			frameBufferGC.fillRect(0, 0, frameBuffer.getWidth(),
					frameBuffer.getHeight());
			canvasAreaGC.drawImage(frameBuffer, 0, 0, canvasArea);
		}

		initialCanvas.flush();
	}

	public void slide(int action) {
		if (canvasArea == null || canvasArea.getSize().width == 0
				|| canvasArea.getSize().height == 0) {
			return;
		}

		BufferedImage initialCanvas = new BufferedImage(
				canvasArea.getSize().width, canvasArea.getSize().height,
				BufferedImage.TYPE_INT_ARGB);
		BufferedImage frameBuffer = new BufferedImage(
				canvasArea.getSize().width, canvasArea.getSize().height,
				BufferedImage.TYPE_INT_ARGB);

		Graphics2D initialCanvasGC = (Graphics2D) initialCanvas
				.createGraphics();
		Graphics2D frameBufferGC = (Graphics2D) frameBuffer.createGraphics();
		Graphics2D canvasAreaGC = (Graphics2D) canvasArea.getGraphics();

		canvasArea.paintAll(initialCanvasGC);
		frameBufferGC.setColor(canvasArea.getComponentAt(0, 0).getBackground());

		int x;
		int step = canvasArea.getWidth() / 15;

		if (action == DISAPPEAR) {
			x = 0;
			while (x <= canvasArea.getSize().width) {
				frameBufferGC.fillRect(0, 0, frameBuffer.getWidth(),
						frameBuffer.getHeight());
				frameBufferGC.drawImage(initialCanvas, x, 0, canvasArea);
				canvasAreaGC.drawImage(frameBuffer, 0, 0, canvasArea);
				x += step;
			}
		} else {
			x = canvasArea.getSize().width;
			while (x > 0) {
				frameBufferGC.fillRect(0, 0, frameBuffer.getWidth(),
						frameBuffer.getHeight());
				frameBufferGC.drawImage(initialCanvas, x, 0, canvasArea);
				canvasAreaGC.drawImage(frameBuffer, 0, 0, canvasArea);
				x -= step;
			}
		}
	}
}
